//
//  AppDelegate.m
//  keyboardtest
//
//  Created by  JasonLee on 2021/12/30.
//

#import "AppDelegate.h"
#import <IOKit/hidsystem/IOHIDLib.h> 
CGEventRef mycallBack(CGEventTapProxy  proxy,
                      CGEventType type, CGEventRef  event, void * __nullable userInfo) {
    UniCharCount actualStringLength = 0;
       UniChar inputString[128];
       CGEventKeyboardGetUnicodeString(event, 128, &actualStringLength, inputString);
       NSString* inputedString = [[NSString alloc] initWithBytes:(const void*)inputString length:actualStringLength encoding:NSUTF8StringEncoding];
       
       CGEventFlags flag = CGEventGetFlags(event);
       NSLog(@"inputed string:%@, flags:%lld", inputedString, flag);
    return  event;
}
@interface AppDelegate ()

@property(atomic, strong) id gloableM;
@property(atomic, strong) id localM;

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {


if(@available(macos 10.15, *))
{
    IOHIDAccessType theType = IOHIDCheckAccess(kIOHIDRequestTypeListenEvent);
    NSLog(@"IOHIDCheckAccess = %d", theType);
    switch (theType)
    {
        case kIOHIDAccessTypeGranted:
            //同意
            break;
        case kIOHIDAccessTypeDenied:
        {
            //拒绝
            NSString *urlString = @"x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent";
            [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:urlString]];
            break;
        }
        case kIOHIDAccessTypeUnknown:
        {
            //未弹过提示框
            bool result = IOHIDRequestAccess(kIOHIDRequestTypeListenEvent);
            NSLog(@"IOHIDRequestAccess result = %d", result);
            break;
        }
        default:
            break;
    }
}
    // Insert code here to initialize your application
    CFRunLoopRef theRL = CFRunLoopGetCurrent();
    CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap ,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventFlagsChanged),&mycallBack,NULL);
    CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, keyUpEventTap, 1);
    
    CFRunLoopAddSource(theRL, keyUpRunLoopSourceRef, kCFRunLoopCommonModes);
    CFRelease(keyUpRunLoopSourceRef);
    CFRelease(keyUpEventTap);
//    CGEventTapCreate(CGEventTapLocation tap,
//        CGEventTapPlacement place, CGEventTapOptions options,
//        CGEventMask eventsOfInterest, CGEventTapCallBack callback,
//        void * __nullable userInfo)
//    | CGEventMaskBit(kCGEventFlagsChanged)
//    CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap
//                                                   ,kCGEventTapOptionDefault,CGEventMaskBit(kCGEventKeyDown) ,&mycallBack,(__bridge void *)(self));
////fjldsajlkfsa
//    CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, keyUpEventTap, 1);
//    CFRelease(keyUpEventTap);
//    CFRunLoopAddSource(theRL, keyUpRunLoopSourceRef, kCFRunLoopCommonModes);
//    CFRelease(keyUpRunLoopSourceRef);
    
//    CFRunLoopRef runloop = CFRunLoopGetCurrent();
//    CFMachPortRef keyupEvent = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly , CGEventMaskBit(kCGEventKeyDown), &mycallBack,NULL);
//    CFRunLoopSourceRef ret = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, keyupEvent, 0);
//    CFRelease(keyupEvent);
//    CFRunLoopAddSource(runloop, ret, kCFRunLoopDefaultMode);
//    CFRelease(ret);
    CFStringRef keys[] = {kAXTrustedCheckOptionPrompt};
    CFBooleanRef values[] = {kCFBooleanTrue};

    //keyCallBacks：字典键值的回调，系统预设值kCFTypeDictionaryKeyCallBacks适用于所有CFTypes类型；当KEY是可变类型时，需要保存一个不可变的副本，需要使用kCFCopyStringDictionaryKeyCallBacks；
    //valueCallBacks:系统预设值kCFTypeDictionaryValueCallBacks适用于所有CFTypes类型
    CFDictionaryRef dic = CFDictionaryCreate(CFAllocatorGetDefault(), (const void**)keys, (const void**)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
//    AXErrorfjldsajlkfsva
    BOOL ret1 = AXIsProcessTrustedWithOptions(dic);
    if (ret1) {
        NSLog(@"====");
    }else {
        NSLog(@"=0000==");
    }
    [NSEvent removeMonitor:self.gloableM];
    [NSEvent removeMonitor:self.localM];

    self.gloableM = [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^(NSEvent * _Nonnull event) {
            NSLog(@"====%@",event);
    }];
    self.localM = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown|NSEventMaskFlagsChanged handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
        NSLog(@"%@",event);
//        NSEventModifierFlagCapsLock           = 1 << 16, // Set if Caps Lock key is pressed.
//        NSEventModifierFlagShift              = 1 << 17, // Set if Shift key is pressed.
//        NSEventModifierFlagControl            = 1 << 18, // Set if Control key is pressed.
//        NSEventModifierFlagOption             = 1 << 19, // Set if Option or Alternate key is pressed.
//        NSEventModifierFlagCommand            = 1 << 20, // Set if Command key is pressed.
//        NSEventModifierFlagNumericPad         = 1 << 21, // Set if any key in the numeric keypad is pressed.
//        NSEventModifierFlagHelp               = 1 << 22, // Set if the Help key is pressed.
//        NSEventModifierFlagFunction           = 1 << 23, // Set if any function key is pressed.
//
//        // Used to retrieve only the device-independent modifier flags, allowing applications to mask off the device-dependent modifier flags, including event coalescing information.
//        NSEventModifierFlagDeviceIndependentFlagsMask    = 0xffff0000UL
//        NSWindow
//        NSString * str = [event charactersByApplyingModifiers:event.modifierFlags];111111111
        NSUInteger flags = event.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask;
        if (flags == NSEventModifierFlagCapsLock) {
            NSLog(@"caps");
        } else if (flags == NSEventModifierFlagShift) {
            NSLog(@"shift");
        }else if (flags == NSEventModifierFlagControl) {
            NSLog(@"ctl");
        }else if (flags == NSEventModifierFlagOption) {
            NSLog(@"OPTION");
        }else if (flags == NSEventModifierFlagCommand) {
            NSLog(@"cmd");
        }else if (flags == NSEventModifierFlagNumericPad) {
            NSLog(@"number");
        }else if (flags == NSEventModifierFlagHelp) {
            NSLog(@"help");
        }else if (flags == NSEventModifierFlagFunction) {
            NSLog(@"function");
        }else if (flags == NSEventModifierFlagDeviceIndependentFlagsMask) {
            NSLog(@"Independent");
        }
        return  event;
    }];
}


- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}


@end
